import java.awt.Point;

public class PLPatternParallel extends PLPattern {
	public PLPatternParallel() {
		super("Parallel");
	}
	
	
	/*
	 * Function to validate response and compute confidence for given set of query and response
	 * Returns the confidence with which query and response are parallel 
	 * if confidence is lower than 0.5 compute new better response shape
	 */
	
	public float ValidateResponse(PLShape query, PLShape response, PLOutShape outBetterMatch) {
		
		
		float confidence = confParallel(query.GetLines(), response.GetLines());
		

		
		
		// if the confidence is low, possible choose to return a new shape that better fits the pattern
		
		if (confidence >= 0.5){
			return confidence;
		} 
		else  // write the code to compute new shape
		{
		//angle divided by PI/2 is essentially confidence, so to compute new angle, find product of
		// new confidence and PI/2
			
		float angle_new = (float) (0.5f*(Math.PI/2));	
		
		//how to compute new shape with the angle given?
			
		}		
		return confidence;		
	}
	
	/*
	 * Function to improve upon the response to query, new response is also passes and need
	 * to check which response is better
	 * right now implementation is just checking confidence value with both the response shapes 
	 * and return the shape with bigger confidence value
	 */
	
	public PLShape ImproveResponse(PLShape query, PLShape responseOrig, PLShape responseNew , PLOutShape outBetterMatch){
		float confOrig =0f;
		float confNew = 0f;
		
		confOrig = ValidateResponse(query, responseOrig, outBetterMatch);
		confNew = ValidateResponse(query, responseNew, outBetterMatch);
		
		if (confOrig >= confNew){
			return responseOrig;
		}
		else{
			return responseNew;
		}

	}
	
	
    public float BuildResponse(PLShape query, PLOutShape response){
    	float confidence = 0;
    	
    	switch(query.GetShapeId()){
		
    	case kLine:
    		//return parallel line
    		PLLine line1 = (PLLine)query;
    		Point startL = line1.GetStart();
    		Point endL = line1.GetEnd();
    		startL.x +=10;
    		endL.x +=10;
    		PLLine resL = new PLLine(startL,endL);
    		response.SetShape(resL);  
    		confidence =1;
    		break;
    		
		case kTriangle: 
		    //return parallel triangle
			PLIsTriangle tri = (PLIsTriangle)query;
			Point startT = tri.GetStart();
			Point endT = tri.GetEnd();
			float widthT = tri.GetWidth();
			startT.x +=20;
    		endT.x +=20;
    		PLIsTriangle resT = new PLIsTriangle(startT,endT,widthT);
    		response.SetShape(resT);
    		confidence =1;
    		break;
			
		case kRect: 
			//return parallel rectangle
			PLRect rect = (PLRect)query;
			Point startR = rect.GetStart();
			Point endR = rect.GetEnd();
			startR.x +=20;
    		endR.x +=20;
    		PLRect resR = new PLRect(startR,endR);
    		response.SetShape(resR);
    		confidence =1;
    		break;
    		
		case kEllipse:
			//return parallel ellipse
			PLEllipse ell = (PLEllipse)query;
			Point startE = ell.GetStart();
			Point endE = ell.GetEnd();
			startE.x +=20;
    		endE.x +=20;
    		PLEllipse resE = new PLEllipse(startE,endE);
    		response.SetShape(resE);
    		confidence =1;
    		break;
    	}
    	
    	return confidence;
    }
	
	
	public float confParallel(PLLine line1, PLLine line2){
		float conf;
		PLDebug.Log("Inside isParallel single line\n");
		PLDebug.Log("Lines are NOT parallel\n");
		conf = 1 - (float)angleBtwLines(line1,line2);
		
		return conf;
	}
	
	
	
	
	public float confParallel(PLLine[] lines1, PLLine[] lines2){
		float conf=0;
		float confSingle=0;
		float confTotal = 0;
		PLDebug.Log("Inside isParallel multi lins\n");
		
		int l1 = lines1.length;
		int l2 = lines2.length;
		int total = l1*l2;
		
		if (total == 0) {
		 PLDebug.Warn("Bad total");
		 return 0;
		}
		
		for (int i=0;i<l1;i++){
			for (int j=0;j<l2;j++){
				confSingle = confParallel(lines1[i],lines2[j]) ;
				confTotal += confSingle;
			}
		}
		
		conf = confTotal/total;		
		return conf;
		
	}
		
	
	// Calculates the angle formed between two lines
    public static double angleBtwLines(PLLine line1, PLLine line2)
    {   
 
        double angle_mod = Math.abs(line1.GetSlopeAngle() - line2.GetSlopeAngle());
        double angle = angle_mod/(Math.PI);
        
        return angle;
    }
				
}

